package lac.serviceuint.job;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.quartz.DisallowConcurrentExecution;
import org.quartz.InterruptableJob;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.UnableToInterruptJobException;

import lac.model.core.util.UUIDUtil;
import lac.serviceuint.ServiceUnitExecuter;
import lac.serviceuint.job.cfg.ServiceUnitJob;
import lac.serviceuint.job.cfg.ServiceUnitJobParam;
import lac.serviceuint.tool.StringToTypeInstantiation;


@DisallowConcurrentExecution
public class JobHandle implements Job,InterruptableJob{

	private ServiceUnitExecuter serviceUnitExecuter;
	private ServiceUnitJob job;
	private List<JobInterceptor> interceptors = new ArrayList<>();
	private ThreadLocal<Map<JobVarKey,Object>> jobVar = new ThreadLocal<>();
	private enum JobVarKey{execId,params,serviceUnitJob}
	private Thread jobThread;
	
	public JobHandle(ServiceUnitJob job) {
		super();
		this.job = job;
	}

	@Override
	public void execute(JobExecutionContext context){
		jobThread = Thread.currentThread();
		String execId = UUIDUtil.generateUUID();
		Object[] params = null;
		Map<JobVarKey,Object> jobVarMap = new LinkedHashMap<>();
		jobVarMap.put(JobVarKey.execId, execId);
		jobVarMap.put(JobVarKey.params, params);
		jobVarMap.put(JobVarKey.serviceUnitJob, job);
		jobVar.set(jobVarMap);
		try {
			String serviceUnitName = job.getServiceUnitName();
			String methodName = job.getMethodName();
			List<ServiceUnitJobParam> jobParams = job.getParams();
			List<Object> paramList = new ArrayList<>();
			if(jobParams != null){
				for(ServiceUnitJobParam jobParam:jobParams){
					Object value = null;
					value = StringToTypeInstantiation.instance(jobParam.getJavaClassType(), jobParam.getDefalutValue());
					while(jobParam.getIndex()>(paramList.size())){
						paramList.add(null);
					}
					paramList.add(jobParam.getIndex(),value);
					
				}
			}
			params=paramList.toArray();
			
			for(JobInterceptor interceptor:interceptors){
				interceptor.beforeExecute(execId,job, params);
			}
			serviceUnitExecuter.execute(serviceUnitName, methodName, params);
			for(JobInterceptor interceptor:interceptors){
				interceptor.afterExecute(execId,job, params, null);
			}
		} catch (Exception e) {
			for(JobInterceptor interceptor:interceptors){
				interceptor.afterExecute(execId,job, params, e);
			}
			e.printStackTrace();
		}finally{
			jobVar.remove();
		}
	}

	public ServiceUnitExecuter getServiceUnitExecuter() {
		return serviceUnitExecuter;
	}

	public void setServiceUnitExecuter(ServiceUnitExecuter serviceUnitExecuter) {
		this.serviceUnitExecuter = serviceUnitExecuter;
	}

	
	public ServiceUnitJob getJob() {
		return job;
	}

	public void setJob(ServiceUnitJob job) {
		this.job = job;
	}

	public void addTaskInterceptor(Collection<JobInterceptor> interceptors){
		this.interceptors.addAll(interceptors);
	}
	public void addTaskInterceptor(JobInterceptor interceptor){
		this.interceptors.add(interceptor);
	}

	@Override
	public void interrupt() throws UnableToInterruptJobException {
		if(jobThread!=null){
			jobThread.interrupt();
		}
		/*String execId = null;
		Object[] params = null;
		if(jobVar.get()!=null){
			execId = jobVar.get().get(JobVarKey.execId)==null?null:(String) jobVar.get().get(JobVarKey.execId);
			params = jobVar.get().get(JobVarKey.params)==null?null:(Object[]) jobVar.get().get(JobVarKey.params);
		}*/
		/*for(JobInterceptor interceptor:interceptors){
			interceptor.interruptExecute(execId,job, params);
		}*/
		
	}
	
	
}
